package edu.kit.csl.pisa.training.eva2;

/*
This file is part of the PISA Alignment Tool.

Copyright (C) 2013
Karlsruhe Institute of Technology
Cognitive Systems Lab (CSL)
Felix Stahlberg

PISA is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

PISA is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with PISA. If not, see <http://www.gnu.org/licenses/>.
*/

import java.io.Serializable;

import edu.kit.csl.pisa.datatypes.Alignment;
import edu.kit.csl.pisa.datatypes.SentenceAlignment;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.mutation.InterfaceMutation;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;

/**
 * This is the abstract superclass for all mutators modifying alignments. It
 * has the same characteristics and purpose as a Adapter (GoF design pattern),
 * but is implemented differently.
 */
abstract public class MutateAlignment implements InterfaceMutation,
		Serializable {
	
	private static final long serialVersionUID = 5797008712992151614L;

	/** 
	 * This method will enable you to clone a given mutation operator. Since
	 * there are no member variables in this class, we can simply return the
	 * this pointer. Implementing subclasses with member variables should
	 * handle this differently.
	 * 
	 * @return The clone
	 */
	@Override
	public Object clone() {
		return this;
	}

    /** 
     * This method allows you to evaluate whether two mutation operators
     * are actually the same. We simply check if the argument is also an
     * instance of MutateAlignment. Implementing subclasses may want to
     * override this method.
     * 
     * @param mutator   The other mutation operator
     */
	@Override
    public boolean equals(Object mutator) {
        return (mutator instanceof MutateAlignment);
    }

    /** 
     * Since we do not need initialization here, this method is empty.
     * {@inheritDoc}
     */
	@Override
    public void init(AbstractEAIndividual individual,
    		InterfaceOptimizationProblem opt){
    	// Nothing to do here
    }

    /**
     * This method will mutate a given AbstractEAIndividual. If the individual
     * doesn't implement {@link InterfaceDataTypeSentenceAlignment} nothing 
     * happens.
     * 
     * @param individual    The individual that is to be mutated
     */
	@Override
    public void mutate(AbstractEAIndividual individual) {
    	if (!(individual instanceof InterfaceDataTypeSentenceAlignment)) {
    		return;
    	}
    	SentenceAlignment align = ((InterfaceDataTypeSentenceAlignment) individual)
    			.getSentenceAlignment(); 
    	assert align.isConsistent();
    	mutate(align.getAlignment());
    	assert align.isConsistent();
    	
    }
	
	/**
	 * Template method (GoF). Mutate an alignment instance. Must be implemented
	 * by subclasses.
	 * 
	 * @param alignment the alignment that is to be mutated
	 */
	abstract protected void mutate(Alignment alignment);

    /** 
     * Since this functionality is not supported, this method is empty.
     * {@inheritDoc}
     */
	@Override
    public void crossoverOnStrategyParameters(AbstractEAIndividual indy1,
    		Population partners) {
        // Nothing to do here
    }

    /* (non-Javadoc)
     * @see eva2.server.go.operators.mutation.InterfaceMutation
     * 		#getStringRepresentation()
     */
	@Override
    public String getStringRepresentation() {
        return "Modify Alignment Mutation";
    }
}
